#include "Effect_Reverb.h"

const int slider_min_high = 200;
// const int slider_max_high = 250;

Effect_Reverb::Effect_Reverb(QWidget *parent)
    : QWidget{parent}
{
    min_tone = 1;
    max_tone = 100;
    step_tone = 1;
    min_fadeback = 1;
    max_fadeback = 100;
    step_fadeback = 1;
    min_wet = -30;
    max_wet = 30;
    step_wet = 0.1;
    min_dry = -30;
    max_dry = 30;
    step_dry = 0.1;
    min_damp = 1;
    max_damp = 100;
    step_damp = 1;

    lab_text_fadeback.setText(tr("Fadeback"));
    lab_text_wet.setText(tr("Wet(dB)"));
    lab_text_dry.setText(tr("Dry(dB)"));
    lab_text_tone.setText(tr("Tone"));
    lab_text_damp.setText(tr("Damping"));

    sli_tone.setRange(0,(int)((max_tone - min_tone) / step_tone));
    sli_tone.setMinimumHeight(slider_min_high);
    sli_fadeback.setRange(0,(int)((max_fadeback - min_fadeback) / step_fadeback));
    sli_fadeback.setMinimumHeight(slider_min_high);
    sli_wet.setRange(0,(int)((max_wet - min_wet) / step_wet));
    sli_wet.setMinimumHeight(slider_min_high);
    sli_dry.setRange(0,(int)((max_dry - min_dry) / step_dry));
    sli_dry.setMinimumHeight(slider_min_high);
    sli_damp.setRange(0,(int)((max_damp - min_damp) / step_damp));
    sli_damp.setMinimumHeight(slider_min_high);

    edit_sli_text_fadeback.setMaximumWidth(50);
    edit_sli_text_tone.setMaximumWidth(50);
    edit_sli_text_wet.setMaximumWidth(50);
    edit_sli_text_dry.setMaximumWidth(50);
    edit_sli_text_damp.setMaximumWidth(50);
    // lab_text_fadeback.setMaximumWidth(60);
    // lab_text_tone.setMaximumWidth(60);
    // lab_text_wet.setMaximumWidth(60);
    // lab_text_dry.setMaximumWidth(60);
    // lab_text_damp.setMaximumWidth(60);

    chk_enable.setChecked(false);
    chk_enable.setMaximumWidth(20);
    lab_text_enable.setText(tr("Enable:"));
    connect(&sli_tone,&QSlider::valueChanged,this,&Effect_Reverb::slot_slider_change_tone);
    connect(&sli_fadeback,&QSlider::valueChanged,this,&Effect_Reverb::slot_slider_change_fadeback);
    connect(&sli_wet,&QSlider::valueChanged,this,&Effect_Reverb::slot_slider_change_wet);
    connect(&sli_dry,&QSlider::valueChanged,this,&Effect_Reverb::slot_slider_change_dry);
    connect(&sli_damp,&QSlider::valueChanged,this,&Effect_Reverb::slot_slider_change_damp);
    connect(&edit_sli_text_tone,&QLineEdit::returnPressed,this,&Effect_Reverb::slot_edit_presed_tone);
    connect(&edit_sli_text_fadeback,&QLineEdit::returnPressed,this,&Effect_Reverb::slot_edit_presed_fadeback);
    connect(&edit_sli_text_wet,&QLineEdit::returnPressed,this,&Effect_Reverb::slot_edit_presed_wet);
    connect(&edit_sli_text_dry,&QLineEdit::returnPressed,this,&Effect_Reverb::slot_edit_presed_dry);
    connect(&edit_sli_text_damp,&QLineEdit::returnPressed,this,&Effect_Reverb::slot_edit_presed_damp);
    connect(&chk_enable,&QCheckBox::clicked,this,&Effect_Reverb::slot_chk_state_changed);
    this->set_param(Tone,min_tone);
    this->set_param(Fadeback,min_fadeback);
    this->set_param(Wet,min_wet);
    this->set_param(Dry,min_dry);
    this->set_param(Damp,min_damp);
    this->set_param(Enable,0);

    // layout.setRowStretch(0,80);
    // layout.setRowStretch(1,10);
    // layout.setRowStretch(2,10);

    layout.addWidget(&chk_enable,0,0,3,1);

    layout.addWidget(&lab_text_wet,2,1,1,1,Qt::AlignCenter);
    layout.addWidget(&edit_sli_text_wet,1,1,1,1,Qt::AlignCenter);
    layout.addWidget(&sli_wet,0,1,1,1,Qt::AlignCenter);

    layout.addWidget(&lab_text_dry,2,2,1,1,Qt::AlignCenter);
    layout.addWidget(&edit_sli_text_dry,1,2,1,1,Qt::AlignCenter);
    layout.addWidget(&sli_dry,0,2,1,1,Qt::AlignCenter);

    layout.addWidget(&lab_text_fadeback,2,3,1,1,Qt::AlignCenter);
    layout.addWidget(&edit_sli_text_fadeback,1,3,1,1,Qt::AlignCenter);
    layout.addWidget(&sli_fadeback,0,3,1,1,Qt::AlignCenter);

    layout.addWidget(&lab_text_tone,2,4,1,1,Qt::AlignCenter);
    layout.addWidget(&edit_sli_text_tone,1,4,1,1,Qt::AlignCenter);
    layout.addWidget(&sli_tone,0,4,1,1,Qt::AlignCenter);

    layout.addWidget(&lab_text_damp,2,5,1,1,Qt::AlignCenter);
    layout.addWidget(&edit_sli_text_damp,1,5,1,1,Qt::AlignCenter);
    layout.addWidget(&sli_damp,0,5,1,1,Qt::AlignCenter);

    setLayout(&layout);
    enable_all(chk_enable.checkState());
}

Effect_Reverb::~Effect_Reverb()
{

}

void Effect_Reverb::enable_all(bool enable)
{
    edit_sli_text_damp.setEnabled(enable);
    edit_sli_text_dry.setEnabled(enable);
    edit_sli_text_fadeback.setEnabled(enable);
    edit_sli_text_tone.setEnabled(enable);
    edit_sli_text_wet.setEnabled(enable);
    sli_damp.setEnabled(enable);
    sli_dry.setEnabled(enable);
    sli_fadeback.setEnabled(enable);
    sli_tone.setEnabled(enable);
    sli_wet.setEnabled(enable);
    lab_text_damp.setEnabled(enable);
    lab_text_dry.setEnabled(enable);
    lab_text_fadeback.setEnabled(enable);
    lab_text_tone.setEnabled(enable);
    lab_text_wet.setEnabled(enable);
}

float Effect_Reverb::set_param(PARAM_NAME param_name, float v)
{
    float ret;
    switch(param_name)
    {
    case Enable:
    {
        if(v == 0.0)
        {
            ret = 0.0;
            chk_enable.setChecked(false);
        }
        else
        {
            ret = 1.0;
            chk_enable.setChecked(true);
        }
    }
    break;
    case Tone:
    {
        if(step_tone < 0.01)
        {
            v = qRound(v*10000.0f) / 10000.0f;
        }
        else if(step_tone < 0.1)
        {
            v = qRound(v*1000.0f) / 1000.0f;
        }
        else if(step_tone < 0)
        {
            v = qRound(v*100.0f) / 100.0f;
        }
        else
        {
            v = qRound(v*10.0f) / 10.0f;
        }
        tone = v;
        ret = v;
        edit_sli_text_tone.setText(QString("%1").arg(v));
        v = (v - min_tone) / step_tone;
        sli_tone.setValue((int)v);
    }
    break;
    case Fadeback:
    {
        if(step_fadeback < 0.01)
        {
            v = qRound(v*10000.0f) / 10000.0f;
        }
        else if(step_fadeback < 0.1)
        {
            v = qRound(v*1000.0f) / 1000.0f;
        }
        else if(step_fadeback < 0)
        {
            v = qRound(v*100.0f) / 100.0f;
        }
        else
        {
            v = qRound(v*10.0f) / 10.0f;
        }
        fadeback = v;
        ret = v;
        edit_sli_text_fadeback.setText(QString("%1").arg(v));
        v = (v - min_fadeback) / step_fadeback;
        sli_fadeback.setValue((int)v);
    }
    break;
    case Wet:
    {
        if(step_wet < 0.01)
        {
            v = qRound(v*10000.0f) / 10000.0f;
        }
        else if(step_wet < 0.1)
        {
            v = qRound(v*1000.0f) / 1000.0f;
        }
        else if(step_wet < 0)
        {
            v = qRound(v*100.0f) / 100.0f;
        }
        else
        {
            v = qRound(v*10.0f) / 10.0f;
        }
        wet = v;
        ret = v;
        edit_sli_text_wet.setText(QString("%1").arg(v));
        v = (v - min_wet) / step_wet;
        sli_wet.setValue((int)v);
    }
    break;
    case Dry:
    {
        if(step_dry < 0.01)
        {
            v = qRound(v*10000.0f) / 10000.0f;
        }
        else if(step_dry < 0.1)
        {
            v = qRound(v*1000.0f) / 1000.0f;
        }
        else if(step_dry < 0)
        {
            v = qRound(v*100.0f) / 100.0f;
        }
        else
        {
            v = qRound(v*10.0f) / 10.0f;
        }
        dry = v;
        ret = v;
        edit_sli_text_dry.setText(QString("%1").arg(v));
        v = (v - min_dry) / step_dry;
        sli_dry.setValue((int)v);
    }
    break;
    case Damp:
    {
        if(step_damp < 0.01)
        {
            v = qRound(v*10000.0f) / 10000.0f;
        }
        else if(step_damp < 0.1)
        {
            v = qRound(v*1000.0f) / 1000.0f;
        }
        else if(step_damp < 0)
        {
            v = qRound(v*100.0f) / 100.0f;
        }
        else
        {
            v = qRound(v*10.0f) / 10.0f;
        }
        damp = v;
        ret = v;
        edit_sli_text_damp.setText(QString("%1").arg(v));
        v = (v - min_damp) / step_damp;
        sli_damp.setValue((int)v);
    }
    break;
    }
    return ret;
}

float Effect_Reverb::get_param(PARAM_NAME param_name)
{
    float v = 0;
    switch(param_name)
    {
        case Enable:
        {
            v = (chk_enable.checkState() != 0) ? 1.0 : 0.0;
        }
        break;
        case Tone:
        {
            v = tone;
        }
        break;
        case Fadeback:
        {
            v = fadeback;
        }
        break;
        case Wet:
        {
            v = wet;
        }
        break;
        case Dry:
        {
            v = dry;
        }
        break;
        case Damp:
        {
            v = damp;
        }
        break;
    }
        return v;
}

void Effect_Reverb::set_title(const QString &title)
{
    // lab_title.setText(title);
}

void Effect_Reverb::slot_slider_change_tone(int v)
{
    float param = min_tone + (max_tone - min_tone) * ((float)v / (float)sli_tone.maximum());
    this->set_param(Tone,param);
    emit sig_param_update(Tone,param);
}

void Effect_Reverb::slot_slider_change_fadeback(int v)
{
    float param = min_fadeback + (max_fadeback - min_fadeback) * ((float)v / (float)sli_fadeback.maximum());
    this->set_param(Fadeback,param);
    emit sig_param_update(Fadeback,param);
}

void Effect_Reverb::slot_slider_change_wet(int v)
{
    float param = (min_wet + (float)v * step_wet);
    this->set_param(Wet,param);
    emit sig_param_update(Wet,param);
}

void Effect_Reverb::slot_slider_change_dry(int v)
{
    float param = min_dry + (max_dry - min_dry) * ((float)v / (float)sli_dry.maximum());
    this->set_param(Dry,param);
    emit sig_param_update(Dry,param);
}

void Effect_Reverb::slot_slider_change_damp(int v)
{
    float param = min_damp + (max_damp - min_damp) * ((float)v / (float)sli_damp.maximum());
    this->set_param(Damp,param);
    emit sig_param_update(Damp,param);
}

void Effect_Reverb::slot_edit_presed_tone()
{
    QString str;
    float param;
    bool ok;
    str = edit_sli_text_tone.text();
    param = str.toFloat(&ok);
    if(ok == true)
    {
        if((param >= min_tone) && (param <= max_tone))
        {
            tone = param;
        }
    }
    this->set_param(Tone,tone);
    emit sig_param_update(Tone,tone);
}

void Effect_Reverb::slot_edit_presed_fadeback()
{
    QString str;
    float param;
    bool ok;
    str = edit_sli_text_fadeback.text();
    param = str.toFloat(&ok);
    if(ok == true)
    {
        if((param >= min_fadeback) && (param <= max_fadeback))
        {
            fadeback = param;
        }
    }
    this->set_param(Fadeback,fadeback);
    emit sig_param_update(Fadeback,fadeback);
}

void Effect_Reverb::slot_edit_presed_wet()
{
    QString str;
    float param;
    bool ok;
    str = edit_sli_text_wet.text();
    param = str.toFloat(&ok);
    if(ok == true)
    {
        if((param >= min_wet) && (param <= max_wet))
        {
            wet = param;
        }
    }
    this->set_param(Wet,wet);
    emit sig_param_update(Wet,wet);
}

void Effect_Reverb::slot_edit_presed_dry()
{
    QString str;
    float param;
    bool ok;
    str = edit_sli_text_dry.text();
    param = str.toFloat(&ok);
    if(ok == true)
    {
        if((param >= min_dry) && (param <= max_dry))
        {
            dry = param;
        }
    }
    this->set_param(Dry,dry);
    emit sig_param_update(Dry,dry);
}

void Effect_Reverb::slot_edit_presed_damp()
{
    QString str;
    float param;
    bool ok;
    str = edit_sli_text_damp.text();
    param = str.toFloat(&ok);
    if(ok == true)
    {
        if((param >= min_damp) && (param <= max_damp))
        {
            damp = param;
        }
    }
    this->set_param(Damp,damp);
    emit sig_param_update(Damp,damp);
}

void Effect_Reverb::slot_chk_state_changed(int state)
{
    enable_all(state);
    emit sig_param_update(Enable,state ? 1 : 0);
}
